package com.easylinkin.sm.permission.impl;

import com.easylinkin.sm.constant.DepartmentConstant;
import com.easylinkin.sm.constant.UserConstant;
import com.easylinkin.sm.permission.jpa.JpaDepartmentPermission;
import com.easylinkin.sm.util.DataPermissionUtils;

import java.util.Objects;
import javax.persistence.criteria.Path;
import lombok.Data;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import site.morn.bean.BeanCaches;
import site.morn.boot.data.entity.OrganizedEntity.Fields;
import site.morn.boot.jpa.JpaPredicate;
import site.morn.exception.ApplicationMessages;
import site.morn.framework.context.AccountContext;
import site.morn.framework.context.DepartmentContextProducer;
import site.morn.framework.entity.BaseDepartment;
import site.morn.framework.entity.BaseUser;

/**
 * 组织机构权限实现类
 *
 * @author wujie
 * @since 0.0.1,  2019/10/17
 */
@Component
@Data
public class SimpleJpaDepartmentPermission implements JpaDepartmentPermission {

  private Long id;

  private boolean isDeep = false;

  private String fieldName = Fields.departmentId;

  private Path path;

  @Override
  public SimpleJpaDepartmentPermission currentDepartment() {
    return this;
  }

  @Override
  public SimpleJpaDepartmentPermission department(Long id) {
    this.id = id;
    return this;
  }

  @Override
  public SimpleJpaDepartmentPermission deep() {
    this.isDeep = true;
    return this;
  }

  @Override
  public SimpleJpaDepartmentPermission foreignKey(String fieldName) {
    this.fieldName = fieldName;
    return this;
  }

  @Override
  public SimpleJpaDepartmentPermission foreignKey(Path path) {
    this.path = path;
    return this;
  }

  @Override
  public <T> Specification<T> specification() {
    return (root, criteriaQuery, criteriaBuilder) -> {
      JpaPredicate predicate = new JpaPredicate(criteriaBuilder);
      //根据传递机构id过滤,id为null则根据当前用户机构过滤
      if (Objects.isNull(this.id)) {
        BaseUser baseUser = AccountContext.currentUser();
        if (Objects.isNull(baseUser)) {
          throw ApplicationMessages.translateException(UserConstant.Error.USER_NO_FOUND);
        }
        this.id = baseUser.getDepartmentId();
        if (Objects.isNull(this.id)) {
          throw ApplicationMessages.translateException(DepartmentConstant.Error.DEPT_NO_FOUND);
        }
      }
      if (Objects.isNull(this.path)) {
        this.path = root.get(this.fieldName);
      }
      if (this.isDeep) {
        DepartmentContextProducer departmentProducer = BeanCaches
            .bean(DepartmentContextProducer.class);
        BaseDepartment department = departmentProducer.get(this.id);
        String searchCode = department.getSearchCode();

        DataPermissionUtils
            .appendSubOrganizationsPredicate(criteriaQuery, criteriaBuilder, predicate, this.path,
                searchCode);
      } else {
        predicate.appendAnd(criteriaBuilder.equal(this.path, this.id));
      }
      return predicate.get();
    };
  }


}
